#include "SoftI2C.h"


/**
 * @brief 软件I2C初始化配置
 * 
 * @param i2c 
 * @param _port 
 * @param scl_pin 
 * @param sda_pin 
 * @param delay_ticks 
 */
void SoftI2C_Init(
    I2C_t *i2c ,
    volatile uint32_t * _port ,     
    uint8_t          scl_pin   ,
    uint8_t          sda_pin ,
    uint8_t delay_ticks 
) 
{
    i2c->port = _port ;
    i2c->scl_pin =  scl_pin ;
    i2c->sda_pin  =  sda_pin ;
    i2c->delay_ticks = delay_ticks ;
    SDA_H();
    SCL_H();
    
    // SoftI2C_Stop(i2c) ;
    // Serv_Delayms(1000);
}

// #pragma GCC push_options
// #pragma GCC optimize ("O2")
void SoftI2C_DelayTik(uint8_t x) {
    uint8_t cnt = x;
    while (cnt>0)cnt--;
}
// #pragma GCC pop_options  // 结束不优化的代码

/**
 * @brief IIC起始信号
 * 
 * @param i2c 
 */
void SoftI2C_Start(I2C_t *i2c) {
    SDA_H();
    IIC_Delay();
    SCL_H();
    IIC_Delay();
    SDA_L() ;
    IIC_Delay();
    SCL_L();
}

/**
 * @brief IIC停止信号
 * 
 * @param i2c 
 */
void SoftI2C_Stop(I2C_t *i2c) {
    SDA_L();
    IIC_Delay();
    SCL_H();
    IIC_Delay();
    SDA_H();
    IIC_Delay();
}

/**
 * @brief I2C发送字节函数
 * 
 * @param i2c  i2c控制器对象
 * @param ch   要发送的字节内容
 */
void SoftI2C_SendByte(I2C_t *i2c ,uint8_t ch)
{
	for(uint8_t i=0;i<8;i++)
	{
        if (ch&(0x80u>>i)) SDA_H();
        else SDA_L();
        IIC_Delay();
        SCL_H();
        IIC_Delay();
        SCL_L();
        IIC_Delay();
	}
    // SoftI2C_ReceiveAck(i2c);

}

/**
 * @brief I2C接收字节函数
 * 
 * @param i2c i2c控制器对象
 * @return uint8_t 接收到的数据
 */
uint8_t SoftI2C_ReceiveByte(I2C_t *i2c ) {
    uint8_t rByte = 0x00;
    for (uint8_t i = 0; i < 8; i++)
    {
        SDA_H();
        IIC_Delay();
        SCL_H();
        IIC_Delay();
        if(SDA()) rByte |= (0x80 >> i);
        IIC_Delay();
        SCL_L();
        IIC_Delay() ;
    }
    return rByte;
}   


#pragma GCC push_options
#pragma GCC optimize ("O0")
/**
 * @brief IIC发送应答信号
 * 
 * @param i2c i2c 控制器对象
 * @param AckBit 
 */
void SoftI2C_SendAck(I2C_t *i2c ,uint8_t AckBit)
{
    if(AckBit !=0) SDA_H();
    else SDA_L();
    IIC_Delay();
    SCL_H();
    IIC_Delay();
    SCL_L();
    IIC_Delay();
    return ;
}

/**
 * @brief I2C接收应答
 * 
 * @param i2c 
 * @return uint8_t 
 */
uint8_t  SoftI2C_ReceiveAck(I2C_t *i2c)
{
	uint8_t AckBit=1;
    SDA_H() ;
    IIC_Delay();
    SCL_H();
    IIC_Delay();
    AckBit=SDA();
    SCL_L();
    IIC_Delay();
    return AckBit;
}
#pragma GCC pop_options  // 结束不优化的代码

uint8_t SoftI2C_Busy(I2C_t *i2c)
{
	if( ((*i2c->port>>i2c->scl_pin )&0x1) && ((*i2c->port>>i2c->sda_pin )&0x1))return 0;
	else return 1;
}

#if(SOFT_I2C_MORE_BYTE_ENABLE == 1)
uint8_t SoftI2C_Write(I2C_t *i2c , uint8_t deviceaddr , uint8_t *buf , uint8_t bytes) {
    SoftI2C_Start(i2c);
    SoftI2C_SendByte(i2c,deviceaddr); // 器件地址
    if(SoftI2C_ReceiveAck(i2c)) return 0;	
    for(uint8_t i =0;i<bytes;++i) {
        SoftI2C_SendByte(i2c,buf[i]); // 发送的数据
        if(SoftI2C_ReceiveAck(i2c)) return 0;	
    }
    SoftI2C_Stop(i2c);
    return 1 ;
}

uint8_t SoftI2C_Read(I2C_t *i2c , uint8_t deviceaddr , uint8_t *buf , uint8_t bytes) {
    SoftI2C_Start(i2c);
    SoftI2C_SendByte(i2c,deviceaddr|0x80); // 器件地址  读数据
    if(SoftI2C_ReceiveAck(i2c)) return 0;	
    for(uint8_t i =0;i<bytes;++i) {
        buf[i] = SoftI2C_ReceiveByte(i2c); // 发送的数据
        if(i==bytes-1) SoftI2C_SendAck(i2c,1);	
        else SoftI2C_SendAck(i2c,0);	
    }
    SoftI2C_Stop(i2c);
    return 1 ;
}
#endif 


// ------------------------------ IIC 设备 ------------------------------
#if( SOFT_I2C_EEPROM_M24M01_RMN6TP_ENABLE == 1 ) 
uint8_t SoftI2C_M24M01_Write(I2C_t *i2c ,uint8_t devaddr , uint16_t addroffset , uint8_t *buf , uint8_t  bytes) {
    // while(SoftI2C_Busy(i2c));
    SoftI2C_Start(i2c);
    SoftI2C_SendByte(i2c,devaddr); // 器件地址
    if(SoftI2C_ReceiveAck(i2c)) return 0;

    SoftI2C_SendByte(i2c,addroffset>>8); // 
    if(SoftI2C_ReceiveAck(i2c)) return 0;

    SoftI2C_SendByte(i2c,addroffset&0XFF); // 
    if(SoftI2C_ReceiveAck(i2c)) return 0;
    for(uint8_t i =0;i<bytes;++i) {
        SoftI2C_SendByte(i2c,buf[i]); // 发送的数据
        if(SoftI2C_ReceiveAck(i2c)) return 0;	
    }
    SoftI2C_Stop(i2c);
    return 1 ;
}

uint8_t SoftI2C_M24M01_Read(I2C_t *i2c ,uint8_t devaddr , uint16_t addroffset , uint8_t *buf , uint8_t  bytes) {
    // while(SoftI2C_Busy(i2c));
    SoftI2C_Start(i2c); 
    SoftI2C_SendByte(i2c,devaddr); // 器件地址
    if(SoftI2C_ReceiveAck(i2c)) return 0;
    

    SoftI2C_SendByte(i2c,addroffset>>8); // 
    if(SoftI2C_ReceiveAck(i2c)) return 0;

    SoftI2C_SendByte(i2c,addroffset&0XFF); // 
    if(SoftI2C_ReceiveAck(i2c)) return 0;
    SoftI2C_Stop(i2c);

    SoftI2C_Start(i2c);
    SoftI2C_SendByte(i2c,devaddr | 0x01); // 器件地址
    if(SoftI2C_ReceiveAck(i2c)) return 0;
    for(uint8_t j =0;j<bytes;++j) {
        buf[j] = SoftI2C_ReceiveByte(i2c); // 发送的数据
        if(j==bytes-1) SoftI2C_SendAck(i2c,1);	
        else SoftI2C_SendAck(i2c,0);	
    }
    SoftI2C_Stop(i2c);
    return 1;
}

#endif 


#if (SOFT_I2C_LM75_ENABLE == 1) 
uint8_t SoftI2C_LM75_Read(I2C_t *i2c ,uint8_t devaddr , uint8_t point , uint8_t *buf ) {
    SoftI2C_Start(i2c); 
    SoftI2C_SendByte(i2c,devaddr); // 器件地址
    if(SoftI2C_ReceiveAck(i2c)) return 0;

    SoftI2C_SendByte(i2c,point); // 
    if(SoftI2C_ReceiveAck(i2c)) return 0;
    SoftI2C_Stop(i2c);

    SoftI2C_Start(i2c);
    SoftI2C_SendByte(i2c,devaddr | 0x01); // 器件地址
    if(SoftI2C_ReceiveAck(i2c)) return 0;

    buf[0] = SoftI2C_ReceiveByte(i2c); // 发送的数据
    SoftI2C_SendAck(i2c,0);

    buf[1] = SoftI2C_ReceiveByte(i2c); // 发送的数据
    SoftI2C_SendAck(i2c,1);

    SoftI2C_Stop(i2c);
    return 1;
}
#endif 



#if( SOFT_I2C_AHT10_ENABLE == 1) 
uint8_t SoftI2C_AHT10_Status(I2C_t *i2c ) {
    uint8_t rt  = 0 ;
    SoftI2C_Start(i2c); 
    SoftI2C_SendByte(i2c,0x71); // 器件地址
    if(SoftI2C_ReceiveAck(i2c)) return 0;

    rt = SoftI2C_ReceiveByte(i2c); // 发送的数据
    SoftI2C_SendAck(i2c,1);
    SoftI2C_Stop(i2c);
}


uint8_t SoftI2C_AHT10_Init(I2C_t *i2c ) {
    // Serv_Delayms(1000) ;
    SoftI2C_Start(i2c); 
    SoftI2C_SendByte(i2c,0x70); // 器件地址
    if(SoftI2C_ReceiveAck(i2c)) return 0;

    SoftI2C_SendByte(i2c,0xe1); 
    if(SoftI2C_ReceiveAck(i2c)) return 0;

    SoftI2C_SendByte(i2c,0x08); 
    if(SoftI2C_ReceiveAck(i2c)) return 0;

    SoftI2C_SendByte(i2c,0x00); 
    if(SoftI2C_ReceiveAck(i2c)) return 0;

    SoftI2C_Stop(i2c); 

    return 1 ;
}

uint8_t SoftI2C_AHT10_Run(I2C_t *i2c  ) {
    SoftI2C_Start(i2c); 
    SoftI2C_SendByte(i2c,0x70); // 器件地址
    if(!SoftI2C_ReceiveAck(i2c)) return 0;

    SoftI2C_SendByte(i2c,0xac); 
    if(!SoftI2C_ReceiveAck(i2c)) return 0;

    SoftI2C_SendByte(i2c,0x33); 
    if(!SoftI2C_ReceiveAck(i2c)) return 0;

    SoftI2C_SendByte(i2c,0x00); 
    if(!SoftI2C_ReceiveAck(i2c)) return 0;

    SoftI2C_Stop(i2c);

    return 1 ;
}


uint8_t SoftI2C_AHT10_Get(I2C_t *i2c ,int32_t *humidity , int32_t *temperature) {
    uint8_t rt = 0;
    uint8_t buf[6] ;
    // 触发测量
    // rt=  SoftI2C_AHT10_Run(i2c);
    // Serv_Delayms(1000) ;
    
    // 读取数据
    SoftI2C_Start(i2c); 
    SoftI2C_SendByte(i2c,0x71); // 器件地址
    if(!SoftI2C_ReceiveAck(i2c)) {
        return 0;
    }

    buf[0] = SoftI2C_ReceiveByte(i2c); SoftI2C_SendAck(i2c,0);	
    buf[1] = SoftI2C_ReceiveByte(i2c); SoftI2C_SendAck(i2c,0);	
    buf[2] = SoftI2C_ReceiveByte(i2c); SoftI2C_SendAck(i2c,0);	
    buf[3] = SoftI2C_ReceiveByte(i2c); SoftI2C_SendAck(i2c,0);	
    buf[4] = SoftI2C_ReceiveByte(i2c); SoftI2C_SendAck(i2c,0);	
    buf[5] = SoftI2C_ReceiveByte(i2c); SoftI2C_SendAck(i2c,1);

    SoftI2C_Stop(i2c);

    if((buf[0] & 0x80u)) {
        *humidity  = buf[1]<<12 ;
        *humidity |= buf[2]<<4 ;
        *humidity |= buf[3]>>4 ;

        *temperature  = buf[3]<<16 ;
        *temperature |= buf[4]<<8 ;
        *temperature |= buf[5] ;
        return 1 ;
    }

    return 0 ;
}

#endif 



